package com.qen.encrypt.utils;

import cn.hutool.core.codec.Base64;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.KeyUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.crypto.asymmetric.KeyType;
import cn.hutool.crypto.asymmetric.RSA;
import cn.hutool.crypto.asymmetric.Sign;
import cn.hutool.crypto.asymmetric.SignAlgorithm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.security.KeyPair;

/**
 * 参数加密工具类:RSA_ECB
 *
 * @author licz
 * @data 2025年05月28日 3:00 PM
 * @version 1.0.0
 */
public class RSAUtils implements ParamEncrypt, SignCheck {
    private final Logger log = LoggerFactory.getLogger(getClass());

    private RSA rsa;

    public RSAUtils() {
    }

    public RSAUtils(byte[] privateKey, byte[] publicKey) {
        rsa = SecureUtil.rsa(privateKey, publicKey);
    }

    public RSAUtils(String privateKeyBase64, String publicKeyBase64) {
        rsa = SecureUtil.rsa(privateKeyBase64, publicKeyBase64);
    }

    @Override
    public void createKey(String outPath) {

        final KeyPair pair = KeyUtil.generateKeyPair(SignAlgorithm.MD5withRSA.getValue());
        final byte[] privateKey = pair.getPrivate().getEncoded();
        final byte[] publicKey = pair.getPublic().getEncoded();
        rsa = SecureUtil.rsa(privateKey, publicKey);
        if (!outPath.endsWith(File.separator)) {
            outPath += File.separator;
        }
        FileUtil.writeBytes(privateKey, outPath + "rsa.pri.pem");
        FileUtil.writeBytes(publicKey, outPath + "rsa.pub.pem");
        log.info("公钥：\n{}", rsa.getPublicKeyBase64());
        log.info("私钥：\n{}", rsa.getPrivateKeyBase64());
    }

    @Override
    public String sign(String str) {
        byte[] data = StrUtil.utf8Bytes(str);
        SignAlgorithm signAlgorithm = SignAlgorithm.MD5withRSA;
//        SignAlgorithm signAlgorithm = SignAlgorithm.valueOf(Algorithm.MD5withRSA.getValue());
        Sign sign = SecureUtil.sign(signAlgorithm, rsa.getPrivateKeyBase64(), rsa.getPublicKeyBase64());
        byte[] b = sign.sign(data);
        return Base64.encode(b);
//        return sign.signHex(data);
    }

    @Override
    public boolean verify(String srcData, String si) {
        SignAlgorithm signAlgorithm = SignAlgorithm.MD5withRSA;
//        SignAlgorithm signAlgorithm = SignAlgorithm.valueOf(Algorithm.MD5withRSA.getValue());
        Sign sign = SecureUtil.sign(signAlgorithm, rsa.getPrivateKeyBase64(), rsa.getPublicKeyBase64());
        byte[] data = StrUtil.utf8Bytes(srcData);
        return sign.verify(data, Base64.decode(si));
    }

    @Override
    public String pubEncrypt(byte[] data) {
        String encrypt = rsa.encryptBase64(data, KeyType.PublicKey);
        return encrypt;
    }

    @Override
    public String pubEncrypt(String data) {
        return pubEncrypt(StrUtil.bytes(data, CharsetUtil.CHARSET_UTF_8));
    }

    @Override
    public byte[] priDecrypt(byte[] data) {
        final byte[] decrypt = rsa.decrypt(data, KeyType.PrivateKey);
        return decrypt;
    }

    @Override
    public String priDecrypt(String data) {
        return rsa.decryptStr(data, KeyType.PrivateKey);
    }

    @Override
    public String priEncrypt(byte[] data) {
        String encrypt = rsa.encryptBase64(data, KeyType.PrivateKey);
        return encrypt;
    }

    @Override
    public String priEncrypt(String data) {
        return priEncrypt(StrUtil.bytes(data, CharsetUtil.CHARSET_UTF_8));
    }

    @Override
    public byte[] pubDecrypt(byte[] data) {
        final byte[] decrypt = rsa.decrypt(data, KeyType.PublicKey);
        return decrypt;
    }

    @Override
    public String pubDecrypt(String data) {
        return rsa.decryptStr(data, KeyType.PublicKey);
    }

}
